#pragma once
#ifndef SDEF_INST
#define SDEF_INST

#include <SypX/SypX.h>
#include "Actor.h"

namespace SheepDefence
{
	enum staminaState
	{
		NORMAL,
		TIRED
	};

	enum pathingState
	{
		OK,
		BANGING
	};
	
	enum instanceState
	{
		UNSPAWNED,	// Wolf
		IDLE,		// Obstacle, Dog, Wolf, Sheep
		RUNNING,	// Wolf, Dog, Sheep
		HUNGRY,		// Wolf
		TRACKING,	// Dog
		FLEEING,	// Wolf, Sheep
		STUCK,		// Dog, Wolf, Sheep
		POUNCING,	// Wolf, Dog
		TARGETED,	// Sheep
		BITING,		// Wolf, Dog
		BITTEN,		// Wolf, Sheep
		DEAD		// Wolf, Sheep
	};

	class Level;
	class Actor;
	class DogInstance;
	class WolfInstance;
	class ObstacleInstance;

	class Instance
	{

	public:

		// Attributes
		Level* level;
		SypX::SpriteInstance* sprite;
		actorType type;
		instanceState state;
		pathingState pathState;
		staminaState stamState;
		float prev_x, prev_y, x, y, dest_x, dest_y, elapsed, stateAge;
		int angle;
		bool changed;
		
		// Constructors and Destructors
		Instance();
		virtual ~Instance();
		
		// Methods
		virtual void move(int, int);
		void changeState(instanceState);
		bool stateChanged();
		virtual void updateAttributes(SypX::Vec2 movement);
		virtual void act(float);
		virtual void respond();
		virtual void boundaryCheck(Actor*);
		virtual bool collide(Instance*);
		virtual void advance(float);
		void updateLevel(Level*);
		void draw();
		virtual Actor* getActor() = 0;

		// Utilities
		static float getAngle(SypX::Vec2&);
		static int genAngle(SypX::Vec2&);
		static float getDist(Instance*, Instance*);
		static float getDist(float diff_x, float diff_y);
		static float getDist(float x, float y, float a_x, float a_y, float b_x, float b_y);
		static void rotateByAngle(SypX::Vec2&, float);
		static void turnRight(SypX::Vec2&);
		static void turnLeft(SypX::Vec2&);
		static bool collision(float start_x, float start_y, float end_x, float end_y, std::vector<ObstacleInstance*>& obstacles, float size, std::vector<ObstacleInstance*>& exceptions);
		static bool collision(float start_x, float start_y, float end_x, float end_y, std::vector<ObstacleInstance*>& obstacles, float size);
		static bool collision(float start_x, float start_y, float end_x, float end_y, std::vector<ObstacleInstance*>& obstacles, WolfInstance* wolf, DogInstance* dog);
		static std::vector<ObstacleInstance*> inObstacle(float x, float y, std::vector<ObstacleInstance*>& obstacles, float size);
	};
}

#endif